/**
 * create by zhike date:2015年3月12日
 */
package com.acooly.module.openapi.client.provider.baofup.marshall;

import com.acooly.core.utils.Reflections;
import com.acooly.core.utils.Strings;
import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.acooly.module.openapi.client.api.marshal.ApiUnmarshal;
import com.acooly.module.openapi.client.api.message.MessageFactory;
import com.acooly.module.openapi.client.provider.baofup.BaoFuPConstants;
import com.acooly.module.openapi.client.provider.baofup.domain.BaoFuPNotify;
import com.acooly.module.openapi.client.provider.baofup.enums.BaoFuPServiceEnum;
import com.acooly.module.openapi.client.provider.baofup.support.BaoFuPAlias;
import com.acooly.module.openapi.client.provider.baofup.utils.BaoFuPSecurityUtil;
import com.acooly.module.openapi.client.provider.baofup.utils.StringHelper;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;

/**
 * @author zhike
 */
@Service
@Slf4j
public class BaoFuPNotifyUnmarshall extends BaoFuPMarshallSupport
        implements ApiUnmarshal<BaoFuPNotify, Map<String, String>> {
    private static final Logger logger = LoggerFactory.getLogger(BaoFuPNotifyUnmarshall.class);

    @Resource(name = "baoFuPMessageFactory")
    private MessageFactory messageFactory;

    @SuppressWarnings("unchecked")
    @Override
    public BaoFuPNotify unmarshal(Map<String, String> notifyMessage, String serviceName) {
        try {
            log.info("异步通知报文{}", notifyMessage);
            try {
                String signature = notifyMessage.get(BaoFuPConstants.SIGNER_TYPE);
                String partnerId = notifyMessage.get(BaoFuPConstants.PARTNER_KEY);
                notifyMessage.remove(BaoFuPConstants.SIGNER_TYPE);
                //验签
                String rSignVStr = StringHelper.coverMap2String(notifyMessage);
                log.info("响应报文SHA-1摘要字串：{}",rSignVStr);
                String rSignature = BaoFuPSecurityUtil.sha1X16(rSignVStr, "UTF-8");
                log.info("响应报文SHA-1摘要结果："+rSignature);
                doVerify(signature,rSignature,partnerId);
                log.info("验签成功");
                //解密数字信封
                String aesKey = "";
                if(notifyMessage.containsKey(BaoFuPConstants.DGTL_ENVLP)) {
                    String dgtlEnvlp = notifyMessage.get(BaoFuPConstants.DGTL_ENVLP);
                    String dgtlEnvlpDecode = doDecodeByProvateKey(dgtlEnvlp,partnerId);
                    //获取aesKey
                    aesKey = StringHelper.getAesKey(dgtlEnvlpDecode);//获取返回的AESkey
                }
                return doUnmarshall(notifyMessage, serviceName,aesKey);
            }catch (Exception e) {
                log.info("Base64代签字符串失败：{}",e.getMessage());
                throw new ApiClientException(e.getMessage());
            }
        } catch (Exception e) {
            throw new ApiClientException("异步通知 解析失败:" + e.getMessage());
        }
    }

    protected BaoFuPNotify doUnmarshall(Map<String, String> message, String serviceName,String aesKey) {
        BaoFuPNotify notify = (BaoFuPNotify) messageFactory.getNotify(BaoFuPServiceEnum.find(serviceName).getKey());
        Set<Field> fields = Reflections.getFields(notify.getClass());
        String key = null;
        for (Field field : fields) {
            Object convertedValue = null;
            BaoFuPAlias baoFuPAlias = field.getAnnotation(BaoFuPAlias.class);
            if (baoFuPAlias == null) {
                continue;
            }
            key = baoFuPAlias.value();
            if (Strings.isBlank(key)) {
                key = field.getName();
            }
            convertedValue = message.get(key);
            if(Strings.isNotBlank((String)convertedValue)) {
                //解密
                boolean isDecode = baoFuPAlias.isDecode();
                if (isDecode) {
                    convertedValue = BaoFuPSecurityUtil.Base64Decode(BaoFuPSecurityUtil.AesDecrypt((String)convertedValue,aesKey));
                }
                Reflections.invokeSetter(notify, field.getName(), convertedValue);
            }
        }
        notify.setService(serviceName);
        return notify;
    }
    public void setMessageFactory(MessageFactory messageFactory) {
        this.messageFactory = messageFactory;
    }
}
